from django.db import models
from apps.orders.models import Order
from django.core.validators import MinValueValidator
from django.utils import timezone
from django.conf import settings
from apps.chefs.models import DjChef 

class Payment(models.Model):
    PAYMENT_METHODS = (
        ('wechat', '微信支付'),
        ('alipay', '支付宝'),
        ('bank', '银行转账')
    )
    
    PAYMENT_STATUS = (
        ('pending', '待支付'),
        ('paid', '已支付'),
        ('failed', '支付失败'),
        ('refunded', '已退款')
    )
    
    order = models.OneToOneField(Order, on_delete=models.CASCADE, related_name='payment')
    transaction_id = models.CharField(max_length=100, unique=True)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    method = models.CharField(max_length=20, choices=PAYMENT_METHODS)
    status = models.CharField(max_length=20, choices=PAYMENT_STATUS, default='pending')
    created_at = models.DateTimeField(auto_now_add=True)
    paid_at = models.DateTimeField(null=True, blank=True)
    
    # 第三方支付返回数据（加密存储）
    raw_response = models.TextField(blank=True)

class Refund(models.Model):
    payment = models.ForeignKey(Payment, on_delete=models.CASCADE, related_name='refunds')
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    reason = models.TextField()
    status = models.CharField(max_length=20, choices=[
        ('requested', '退款申请中'),
        ('processed', '退款处理中'),
        ('completed', '退款完成'),
        ('rejected', '退款被拒')
    ])
    created_at = models.DateTimeField(auto_now_add=True)
    processed_at = models.DateTimeField(null=True, blank=True)




#厨师服务端

class DjChefWallet(models.Model):
    """
    厨师钱包模型 记录余额、冻结金额等
    """
    chef = models.OneToOneField(
        'chefs.DjChef',
        on_delete=models.CASCADE,
        related_name='payment_wallet',
        verbose_name='关联厨师'
    )
    
    # 余额信息
    balance = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0.00,
        validators=[MinValueValidator(0)],
        verbose_name='可用余额'
    )
    
    # 冻结金额（提现中或其他原因）
    frozen_amount = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0.00,
        validators=[MinValueValidator(0)],
        verbose_name='冻结金额'
    )
    
    # 统计信息
    total_earned = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0.00,
        verbose_name='累计收入'
    )
    total_withdrawn = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0.00,
        verbose_name='累计提现'
    )
    
    # 提现限制字段
    daily_withdraw_limit = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=5000.00,
        verbose_name='单日提现限额'
    )
    min_withdraw_amount = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=100.00,
        verbose_name='最低提现金额'
    )
    withdraw_fee_rate = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        default=0.00,
        verbose_name='提现费率(百分比)'
    )
    
    # 安全验证字段
    last_withdraw_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='最后提现时间'
    )
    withdraw_count_today = models.PositiveIntegerField(
        default=0,
        verbose_name='今日提现次数'
    )
    
    # 安全信息
    security_password = models.CharField(
        max_length=128,
        blank=True,
        verbose_name='支付密码(加密存储)'
    )
    is_locked = models.BooleanField(
        default=False,
        verbose_name='是否锁定'
    )
    
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='创建时间'
    )
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='更新时间'
    )
    
    class Meta:
        verbose_name = '厨师支付钱包'
        verbose_name_plural = '厨师支付钱包'
        # 确保一个厨师只能有一个钱包（通过OneToOneField已保证）
        indexes = [
            models.Index(fields=['chef']),
            models.Index(fields=['is_locked']),
        ]
    
    def __str__(self):
        return f"{self.chef} 的钱包 (余额: ¥{self.balance})"
    
    def available_balance(self):
        """可用余额 = 余额 - 冻结金额"""
        return self.balance - self.frozen_amount
    
    def reset_daily_limit(self):
        """重置每日提现次数限制"""
        self.withdraw_count_today = 0
        self.save(update_fields=['withdraw_count_today'])
    
    def can_withdraw(self, amount):
        """检查是否可以提现指定金额"""
        today = timezone.now().date()
        
        # 检查是否是新的一天，重置提现次数
        if self.last_withdraw_at and self.last_withdraw_at.date() < today:
            self.reset_daily_limit()
        
        return (
            not self.is_locked and  # 钱包未锁定
            self.available_balance() >= amount and  # 余额足够
            amount >= self.min_withdraw_amount and  # 达到最低提现金额
            self.withdraw_count_today < 3 and  # 每日最多3次
            amount <= self.daily_withdraw_limit  # 未超过单日限额
        )

class DjChefBankCard(models.Model):
    """厨师银行卡模型"""
    CARD_TYPES = (
        ('debit', '储蓄卡'),
        ('credit', '信用卡')
    )
    chef_id = models.IntegerField(verbose_name="厨师ID")
    
    wallet = models.ForeignKey(
        DjChefWallet,
        on_delete=models.CASCADE,
        related_name='bank_cards',
        verbose_name='关联钱包'
    )
    bank_name = models.CharField(max_length=50, verbose_name='银行名称')
    bank_code = models.CharField(max_length=20, verbose_name='银行代码')
    card_number = models.CharField(max_length=30, verbose_name='完整卡号')
    last_four = models.CharField(max_length=4, verbose_name='卡号后四位')
    card_type = models.CharField(max_length=10, choices=CARD_TYPES, verbose_name='卡类型')
    card_holder = models.CharField(max_length=50, verbose_name='持卡人姓名')
    expire_date = models.CharField(max_length=7, verbose_name='有效期(MM/YYYY)')  # 如 12/2028
    is_default = models.BooleanField(default=False, verbose_name='是否默认卡')
    is_valid = models.BooleanField(default=True, verbose_name='是否有效')  # 新增字段
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    
    class Meta:
        verbose_name = '厨师银行卡'
        verbose_name_plural = '厨师银行卡'
        ordering = ['-is_default', '-created_at']
        # 联合索引：确保同一钱包下卡号唯一
        unique_together = ['wallet', 'card_number']
        indexes = [
            models.Index(fields=['wallet', 'is_default']),
            models.Index(fields=['last_four']),  # 卡号后四位索引
        ]
    
    def save(self, *args, **kwargs):
        # 自动提取卡号后四位
        if self.card_number:
            self.last_four = self.card_number[-4:]
            
        # 自动获取银行名称（如果未提供）
        if not self.bank_name and self.bank_code:
            self.bank_name = self.get_bank_name()
            
        # 如果设为默认卡，取消同钱包下其他卡的默认状态
        if self.is_default:
            DjChefBankCard.objects.filter(
                wallet=self.wallet, 
                is_default=True
            ).exclude(id=self.id if self.id else None).update(is_default=False)
            
        super().save(*args, **kwargs)
    
    def get_bank_name(self):
        """根据银行代码获取银行名称"""
        banks = {
            'ICBC': '中国工商银行',
            'CCB': '中国建设银行',
            'ABC': '中国农业银行',
            'BOC': '中国银行',
            'CMB': '招商银行',
            'CMBC': '中国民生银行',
            'SPDB': '上海浦东发展银行',
            'PAB': '平安银行',
            'BOCOM': '交通银行',
            # 补充其他银行...
        }
        return banks.get(self.bank_code, '未知银行')
    
    def __str__(self):
        return f"{self.bank_name} ({self.last_four}) - {self.card_holder}"
    

class DjWithdrawal(models.Model):
    """
    厨师提现记录模型 记录每次提现申请和状态
    """
    WITHDRAWAL_METHODS = (
        ('wechat', '微信零钱'),
        ('alipay', '支付宝'),
        ('bank', '银行卡'),
    )
    
    WITHDRAWAL_STATUS = (
        ('pending', '处理中'),
        ('processing', '银行处理中'),
        ('completed', '已完成'),
        ('failed', '失败'),
        ('cancelled', '已取消'),
    )
    
    chef_id = models.IntegerField(verbose_name="厨师ID")

    wallet = models.ForeignKey(
        DjChefWallet,
        on_delete=models.CASCADE,
        related_name='withdrawals',
        verbose_name='关联钱包'
    )
    
    # 提现信息
    amount = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        validators=[MinValueValidator(0.01)],
        verbose_name='提现金额'
    )
    fee = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0.00,
        verbose_name='提现手续费'
    )
    method = models.CharField(
        max_length=20,
        choices=WITHDRAWAL_METHODS,
        verbose_name='提现方式'
    )
    status = models.CharField(
        max_length=20,
        choices=WITHDRAWAL_STATUS,
        default='pending',
        verbose_name='提现状态'
    )
    
    # 账户信息 - 根据提现方式关联不同信息
    bank_card = models.ForeignKey(
        'DjChefBankCard',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='withdrawals',
        verbose_name='关联银行卡'
    )

    account_number = models.CharField(
        max_length=50,
        verbose_name='转账号码'
    )
    account_name = models.CharField(
        max_length=50,
        verbose_name='账户姓名'
    )
    
    # 处理信息
    transaction_id = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='外部交易ID'
    )
    failure_reason = models.TextField(
        blank=True,
        verbose_name='失败原因'
    )
    
    # 时间信息
    requested_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='申请时间'
    )
    processed_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='处理时间'
    )
    
    class Meta:
        verbose_name = '提现记录'
        verbose_name_plural = '提现记录'
        ordering = ['-requested_at']
        indexes = [
            models.Index(fields=['wallet', 'status']),
            models.Index(fields=['requested_at']),
            models.Index(fields=['transaction_id']),  # 外部交易ID索引
        ]
    
    def __str__(self):
        return f"{self.wallet.chef} 的提现 ¥{self.amount} ({self.get_status_display()})"
    
    def save(self, *args, **kwargs):
        """保存时自动更新处理时间和手续费"""
        # 首次创建时计算手续费
        if not self.pk and self.amount > 0:
            self.fee = self.amount * (self.wallet.withdraw_fee_rate / 100)
        
        # 状态变更为完成或失败时更新处理时间
        if self.status in ['completed', 'failed'] and not self.processed_at:
            self.processed_at = timezone.now()
            
        super().save(*args, **kwargs)


class DjWalletTransaction(models.Model):
    """
    钱包交易流水模型 记录所有资金变动
    """
    TRANSACTION_TYPES = (
        ('order_income', '订单收入'),
        ('withdrawal', '提现'),
        ('withdrawal_failed', '提现失败退款'),
        ('adjustment', '人工调整'),
        ('bonus', '奖励金'),
    )

    chef_id = models.IntegerField(verbose_name="厨师ID")
    
    wallet = models.ForeignKey(
        DjChefWallet,
        on_delete=models.CASCADE,
        related_name='transactions',
        verbose_name='关联钱包'
    )
    
    # 交易信息
    transaction_type = models.CharField(
        max_length=20,
        choices=TRANSACTION_TYPES,
        verbose_name='交易类型'
    )
    amount = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        verbose_name='交易金额'
    )
    transaction_id = models.CharField(
        max_length=100,
        unique=True,
        verbose_name='交易流水号'  # 新增唯一交易流水号
    )
    
    # 关联业务
    related_withdrawal = models.ForeignKey(
        DjWithdrawal,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name='关联提现'
    )
    related_order = models.ForeignKey(
        'orders.Order',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name='关联订单'
    )
    
    # 备注信息
    note = models.TextField(
        blank=True,
        verbose_name='备注'
    )
    admin_note = models.TextField(
        blank=True,
        verbose_name='管理员备注'
    )
    
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='创建时间'
    )
    
    class Meta:
        verbose_name = '钱包交易流水'
        verbose_name_plural = '钱包交易流水'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['wallet', 'transaction_type']),
            models.Index(fields=['created_at']),
            models.Index(fields=['transaction_id']),  # 交易流水号索引
        ]
    
    def __str__(self):
        return f"{self.get_transaction_type_display()} ¥{self.amount} ({self.wallet.chef})"


